#include <vector>

#include "node_header.h"
#include "hypo.h"

using namespace std;

class node {
	public:

	int status;
	float status_rating;

	int uniq;

	bool lock;

	vector<hypo> hyp;
	vector<node*> linkedNodes; // how very paradoxical.
	vector<node*> linkingNodes;

	node * temp;

		node( int count ) {
			this->status        = __DEFAULT_STATUS;
			this->status_rating = __DEFAULT_STATUS_RATING;
			this->uniq          = 0;
			this->lock			= false;

			hypo h;

			for ( int i = 0; i < count; ++i ) {
				h.setHypo( i );
				this->hyp.push_back( h );
			}
		}
		void lockNode() {
			this->lock = true;
		}
		void unlockNode() {
			this->lock = false;
		}
		bool isLocked() {
			return this->lock;
		}
		bool strictCheck() {
			bool rval = true;
			for ( int i = 0; i < this->linkedNodes.size(); ++i ) {
				temp = this->linkedNodes[i];
				if ( temp->getStatus() == this->getStatus() ) {
					rval = false;
				}
			}
			return rval;
		}
		
		void resetRate() {
			for ( int i = 0; i < this->hyp.size(); ++i ) {
				this->hyp[i].reset();
			}
		}
		int getHypoCount() {
			return this->hyp.size();
		}
		void rateHypoExcept( int h, float r ) {
			if ( h <= this->hyp.size() ) {
				for ( int i = 0; i < this->hyp.size(); ++i ) {
					if ( h != i ) { this->hyp[i].rateHypo( r ); }
				}
			}
		}
		void rateHypo( int h, float r ) {
			if ( h < this->hyp.size() ) {
				this->hyp[h].rateHypo( r );
			}
		}
		float getNegHypoRating( int h ) {
			if ( h <= this->hyp.size() ) {
				return this->hyp[h].getNeg();
			}
		}
		float getPosHypoRating( int h ) {
			if ( h <= this->hyp.size() ) {
				return this->hyp[h].getPos();
			}
		}
		int getID() {
			return this->uniq;
		}
		int getStatus() {
			return this->status;
		}
		bool setStatus( int status ) {
			if ( this->isLocked() ) {
				return false;
			} else {
				this->status = status;
				return true;
			}
		}
		void linkedNode( node * nodeski ) {
			this->linkingNodes.push_back( nodeski );
		}
		void linkNode( node * nodeski ) {
			if ( nodeski == this ) {
				return;
			}
			for ( int i = 0; i < this->linkedNodes.size(); ++i ) {
				if ( linkedNodes[i] == nodeski ) {
					return;
				}
			}
			this->linkedNodes.push_back( nodeski );
			nodeski->linkedNode( this );
			
		}
		float getStatusRating() {
			return this->status_rating;
		}
		int getLinkedCount() {
			return this->linkedNodes.size();
		}
		int getBestStatus() {

			int min = 0;
			int max = 0;
			int current = 0;
			int min_stat = 0;
			int max_stat = 0;
			int current_stat = 0;

			current      = hyp[this->status].getPos();
			current_stat = hyp[this->status].getHypo();

			for ( int i = 0; i < this->hyp.size(); ++i ) {
				if ( hyp[i].getPos() == max && hyp[i].getNeg() < min ) {
					max = hyp[i].getPos();
					max_stat = hyp[i].getHypo();					
				}

				if ( hyp[i].getPos() > max ) {
					max = hyp[i].getPos();
					max_stat = hyp[i].getHypo();
				}
				if ( hyp[i].getNeg() < min ) {
					min = hyp[i].getNeg();
					min_stat = hyp[i].getHypo();
				}
			}
			if ( max == current ) {
				return current_stat;
			} else {
				return max_stat;
			}
		}
		void forceRate( node * nodeski ) {
			nodeski->rateHypoExcept( this->status, 1 );
			nodeski->rateHypo( this->status, -1 );
		}
		void cryForAttn() {
			for ( int i = 0; i < this->linkingNodes.size(); ++i ) {
				linkingNodes[i]->forceRate( this );
			}
		}
		void rerateThings() {
			for ( int i = 0; i < this->linkingNodes.size(); ++i ) {
				linkingNodes[i]->resetRate();
				linkingNodes[i]->cryForAttn();
				this->cryForAttn();
			}
			this->rateNodes();
		}
		void rateNodes() {
			for ( int i = 0; i < this->linkedNodes.size(); ++i ) {
				temp = this->linkedNodes[i];
				temp->rateHypoExcept( this->status, __DEFAULT_UP_VALUE );
				temp->rateHypo( this->status, __DEFAULT_DOWN_VALUE ); 
			}
		}
};

